package com.reebake.ideal.security.oauth2.client;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import com.reebake.ideal.json.util.JsonUtil;
import com.reebake.ideal.servlet.util.WebUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;

import java.util.Collections;
import java.util.Map;
@RequiredArgsConstructor
public class SmartOAuth2AccessTokenResponseClient implements OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
	private final JustAuthFactory justAuthFactory;

	@Override
	public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) {
		ClientRegistration clientRegistration = authorizationCodeGrantRequest.getClientRegistration();
		String registrationId = clientRegistration.getRegistrationId();
		String code = authorizationCodeGrantRequest.getAuthorizationExchange().getAuthorizationResponse().getCode();
		String redirectUri = authorizationCodeGrantRequest.getClientRegistration().getRedirectUri();

		HttpServletRequest request = WebUtil.getRequest();
		Map<String, String[]> parameterMap = request.getParameterMap();
		Map<String, Object> params = MapUtil.newHashMap();
		for(Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
			String[] value = entry.getValue();
			String key = entry.getKey();
			if(ArrayUtil.isNotEmpty(value)) {
				if(value.length == 1) {
					params.put(key, value[0]);
				}else {
					params.put(key, value);
				}
			}
		}
		AuthCallback authCallback = JsonUtil.toBean(JsonUtil.toJsonStr(params), AuthCallback.class);
		AuthResponse<?> authResponse = justAuthFactory.create(registrationId, redirectUri).login(authCallback);
		AuthUser authUser = (AuthUser) authResponse.getData();
		AuthToken authToken = authUser.getToken();
		OAuth2AccessTokenResponse.Builder builder = OAuth2AccessTokenResponse.withToken(authToken.getAccessToken());
		builder.tokenType(OAuth2AccessToken.TokenType.BEARER);
		builder.refreshToken(authToken.getRefreshToken());
		builder.expiresIn(authToken.getExpireIn());

		builder.additionalParameters(Collections.singletonMap(OAuth2ParameterNames.CODE, code));
		builder.additionalParameters(Collections.singletonMap(OAuth2ParameterNames.USER_CODE, authUser));
        return builder.build();
	}

}
